package com.sky.skyopsserver.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.sky.skyopsserver.aspect.ApiOperationLog;
import com.sky.skyopsserver.service.ProjectService;
import com.sky.skyopsserver.utils.PageResponse;
import com.sky.skyopsserver.utils.Response;
import com.sky.skyopsserver.vos.*;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Positive;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * 项目信息控制器
 * 
 * @author Administrator
 * @since 2025-01-17
 */
@Slf4j
@RestController
@RequestMapping("/api/project")
@RequiredArgsConstructor
@Validated
@Tag(name = "项目管理", description = "项目信息的增删改查操作")
public class ProjectController {

    private final ProjectService projectService;

    /**
     * 添加项目
     * 
     * @param reqVO 添加项目请求VO
     * @return 项目ID
     */
    @PostMapping("/add")
    @Operation(summary = "添加项目", description = "新增一个项目信息")
    @ApiOperationLog(description = "添加项目")
    public Response<Long> addProject(@Valid @RequestBody ProjectAddReqVO reqVO) {
        Long projectId = projectService.addProject(reqVO);
        return Response.success(projectId);
    }

    /**
     * 更新项目信息
     * 
     * @param reqVO 更新项目请求VO
     * @return 操作结果
     */
    @PutMapping("/update")
    @Operation(summary = "更新项目信息", description = "修改项目的基本信息")
    @ApiOperationLog(description = "更新项目信息")
    public Response<Boolean> updateProject(@Valid @RequestBody ProjectUpdateReqVO reqVO) {
        Boolean result = projectService.updateProject(reqVO);
        return Response.success(result);
    }

    /**
     * 删除项目
     * 
     * @param id 项目ID
     * @return 操作结果
     */
    @DeleteMapping("/delete/{id}")
    @Operation(summary = "删除项目", description = "根据ID删除指定项目")
    @ApiOperationLog(description = "删除项目")
    public Response<Boolean> deleteProject(
            @Parameter(description = "项目ID", required = true)
            @PathVariable("id") @NotNull(message = "项目ID不能为空") @Positive(message = "项目ID必须为正数") Long id) {
        Boolean result = projectService.deleteProject(id);
        return Response.success(result);
    }

    /**
     * 批量删除项目
     * 
     * @param ids 项目ID列表
     * @return 操作结果
     */
    @DeleteMapping("/batch-delete")
    @Operation(summary = "批量删除项目", description = "根据ID列表批量删除项目")
    @ApiOperationLog(description = "批量删除项目")
    public Response<Boolean> batchDeleteProject(
            @Parameter(description = "项目ID列表", required = true)
            @RequestBody @NotEmpty(message = "项目ID列表不能为空") List<@Positive(message = "项目ID必须为正数") Long> ids) {
        Boolean result = projectService.batchDeleteProject(ids);
        return Response.success(result);
    }

    /**
     * 根据ID查询项目详情
     * 
     * @param id 项目ID
     * @return 项目详情
     */
    @GetMapping("/detail/{id}")
    @Operation(summary = "查询项目详情", description = "根据ID获取项目的详细信息")
    @ApiOperationLog(description = "查询项目详情")
    public Response<ProjectRspVO> getProjectById(
            @Parameter(description = "项目ID", required = true)
            @PathVariable("id") @NotNull(message = "项目ID不能为空") @Positive(message = "项目ID必须为正数") Long id) {
        ProjectRspVO result = projectService.getProjectById(id);
        return Response.success(result);
    }

    /**
     * 根据ID查询项目详情（包含应用列表）
     * 
     * @param id 项目ID
     * @return 项目详情（包含应用列表）
     */
    @GetMapping("/detail-with-apps/{id}")
    @Operation(summary = "查询项目详情（含应用列表）", description = "根据ID获取项目的详细信息，包含应用列表")
    @ApiOperationLog(description = "查询项目详情（含应用列表）")
    public Response<ProjectDetailRspVO> getProjectDetailById(
            @Parameter(description = "项目ID", required = true)
            @PathVariable("id") @NotNull(message = "项目ID不能为空") @Positive(message = "项目ID必须为正数") Long id) {
        ProjectDetailRspVO result = projectService.getProjectDetailById(id);
        return Response.success(result);
    }

    /**
     * 根据编码查询项目
     * 
     * @param code 项目编码
     * @return 项目信息
     */
    @GetMapping("/detail/code/{code}")
    @Operation(summary = "根据编码查询项目", description = "根据项目编码获取项目信息")
    @ApiOperationLog(description = "根据编码查询项目")
    public Response<ProjectRspVO> getProjectByCode(
            @Parameter(description = "项目编码", required = true)
            @PathVariable("code") @NotBlank(message = "项目编码不能为空") String code) {
        ProjectRspVO result = projectService.getProjectByCode(code);
        return Response.success(result);
    }

    /**
     * 分页查询项目列表
     * 
     * @param reqVO 分页查询请求VO
     * @return 分页结果
     */
    @PostMapping("/page")
    @Operation(summary = "分页查询项目列表", description = "根据条件分页查询项目信息")
    @ApiOperationLog(description = "分页查询项目列表")
    public PageResponse<ProjectRspVO> getProjectPage(@Valid @RequestBody ProjectPageReqVO reqVO) {
        IPage<ProjectRspVO> page = projectService.getProjectPage(reqVO);
        return PageResponse.success(page, page.getRecords());
    }

    /**
     * 查询所有项目选项（用于下拉选择）
     * 
     * @return 项目选项列表
     */
    @GetMapping("/options")
    @Operation(summary = "查询项目选项", description = "获取所有项目的选项列表，用于下拉选择")
    @ApiOperationLog(description = "查询项目选项")
    public Response<List<ProjectOptionRspVO>> getAllProjectOptions() {
        List<ProjectOptionRspVO> result = projectService.getAllProjectOptions();
        return Response.success(result);
    }

    /**
     * 查询有应用的项目选项
     * 
     * @return 项目选项列表
     */
    @GetMapping("/options/with-apps")
    @Operation(summary = "查询有应用的项目选项", description = "获取包含应用的项目选项列表")
    @ApiOperationLog(description = "查询有应用的项目选项")
    public Response<List<ProjectOptionRspVO>> getProjectOptionsWithApps() {
        List<ProjectOptionRspVO> result = projectService.getProjectOptionsWithApps();
        return Response.success(result);
    }

    /**
     * 查询空项目选项
     * 
     * @return 项目选项列表
     */
    @GetMapping("/options/empty")
    @Operation(summary = "查询空项目选项", description = "获取不包含应用的项目选项列表")
    @ApiOperationLog(description = "查询空项目选项")
    public Response<List<ProjectOptionRspVO>> getEmptyProjectOptions() {
        List<ProjectOptionRspVO> result = projectService.getEmptyProjectOptions();
        return Response.success(result);
    }

    /**
     * 获取项目统计信息
     * 
     * @return 项目统计信息
     */
    @GetMapping("/statistics")
    @Operation(summary = "获取项目统计信息", description = "获取项目的各项统计数据")
    @ApiOperationLog(description = "获取项目统计信息")
    public Response<ProjectStatisticsRspVO> getProjectStatistics() {
        ProjectStatisticsRspVO result = projectService.getProjectStatistics();
        return Response.success(result);
    }

    /**
     * 检查项目编码是否已存在
     * 
     * @param code 项目编码
     * @param excludeId 排除的项目ID（可选）
     * @return 是否存在
     */
    @GetMapping("/check-code")
    @Operation(summary = "检查项目编码", description = "检查项目编码是否已存在")
    @ApiOperationLog(description = "检查项目编码")
    public Response<Boolean> checkProjectCodeExists(
            @Parameter(description = "项目编码", required = true)
            @RequestParam("code") @NotBlank(message = "项目编码不能为空") String code,
            @Parameter(description = "排除的项目ID")
            @RequestParam(value = "excludeId", required = false) Long excludeId) {
        Boolean result = projectService.checkProjectCodeExists(code, excludeId);
        return Response.success(result);
    }

    /**
     * 检查项目名称是否已存在
     * 
     * @param name 项目名称
     * @param excludeId 排除的项目ID（可选）
     * @return 是否存在
     */
    @GetMapping("/check-name")
    @Operation(summary = "检查项目名称", description = "检查项目名称是否已存在")
    @ApiOperationLog(description = "检查项目名称")
    public Response<Boolean> checkProjectNameExists(
            @Parameter(description = "项目名称", required = true)
            @RequestParam("name") @NotBlank(message = "项目名称不能为空") String name,
            @Parameter(description = "排除的项目ID")
            @RequestParam(value = "excludeId", required = false) Long excludeId) {
        Boolean result = projectService.checkProjectNameExists(name, excludeId);
        return Response.success(result);
    }

    /**
     * 根据名称模糊查询项目
     * 
     * @param name 项目名称关键字
     * @return 项目列表
     */
    @GetMapping("/search/name")
    @Operation(summary = "按名称搜索项目", description = "根据项目名称关键字模糊查询项目")
    @ApiOperationLog(description = "按名称搜索项目")
    public Response<List<ProjectRspVO>> searchProjectByName(
            @Parameter(description = "项目名称关键字", required = true)
            @RequestParam("name") @NotBlank(message = "项目名称关键字不能为空") String name) {
        List<ProjectRspVO> result = projectService.searchProjectByName(name);
        return Response.success(result);
    }

    /**
     * 根据编码模糊查询项目
     * 
     * @param code 项目编码关键字
     * @return 项目列表
     */
    @GetMapping("/search/code")
    @Operation(summary = "按编码搜索项目", description = "根据项目编码关键字模糊查询项目")
    @ApiOperationLog(description = "按编码搜索项目")
    public Response<List<ProjectRspVO>> searchProjectByCode(
            @Parameter(description = "项目编码关键字", required = true)
            @RequestParam("code") @NotBlank(message = "项目编码关键字不能为空") String code) {
        List<ProjectRspVO> result = projectService.searchProjectByCode(code);
        return Response.success(result);
    }

    /**
     * 验证项目编码格式
     * 
     * @param code 项目编码
     * @return 是否有效
     */
    @GetMapping("/validate-code")
    @Operation(summary = "验证项目编码格式", description = "验证项目编码是否符合格式要求")
    @ApiOperationLog(description = "验证项目编码格式")
    public Response<Boolean> validateProjectCode(
            @Parameter(description = "项目编码", required = true)
            @RequestParam("code") @NotBlank(message = "项目编码不能为空") String code) {
        Boolean result = projectService.validateProjectCode(code);
        return Response.success(result);
    }

    /**
     * 获取所有项目编码列表
     * 
     * @return 项目编码列表
     */
    @GetMapping("/codes")
    @Operation(summary = "获取项目编码列表", description = "获取所有项目的编码列表")
    @ApiOperationLog(description = "获取项目编码列表")
    public Response<List<String>> getAllProjectCodes() {
        List<String> result = projectService.getAllProjectCodes();
        return Response.success(result);
    }

    /**
     * 获取所有项目名称列表
     * 
     * @return 项目名称列表
     */
    @GetMapping("/names")
    @Operation(summary = "获取项目名称列表", description = "获取所有项目的名称列表")
    @ApiOperationLog(description = "获取项目名称列表")
    public Response<List<String>> getAllProjectNames() {
        List<String> result = projectService.getAllProjectNames();
        return Response.success(result);
    }

    /**
     * 移动应用到指定项目
     * 
     * @param applicationIds 应用ID列表
     * @param targetProjectId 目标项目ID
     * @return 操作结果
     */
    @PostMapping("/move-apps")
    @Operation(summary = "移动应用到项目", description = "将指定应用移动到目标项目")
    @ApiOperationLog(description = "移动应用到项目")
    public Response<Boolean> moveApplicationsToProject(
            @Parameter(description = "应用ID列表", required = true)
            @RequestParam("applicationIds") @NotEmpty(message = "应用ID列表不能为空") List<@Positive(message = "应用ID必须为正数") Long> applicationIds,
            @Parameter(description = "目标项目ID", required = true)
            @RequestParam("targetProjectId") @NotNull(message = "目标项目ID不能为空") @Positive(message = "目标项目ID必须为正数") Long targetProjectId) {
        Boolean result = projectService.moveApplicationsToProject(applicationIds, targetProjectId);
        return Response.success(result);
    }

    /**
     * 从项目中移除应用
     * 
     * @param applicationIds 应用ID列表
     * @param projectId 项目ID
     * @return 操作结果
     */
    @PostMapping("/remove-apps")
    @Operation(summary = "从项目移除应用", description = "从指定项目中移除应用")
    @ApiOperationLog(description = "从项目移除应用")
    public Response<Boolean> removeApplicationsFromProject(
            @Parameter(description = "应用ID列表", required = true)
            @RequestParam("applicationIds") @NotEmpty(message = "应用ID列表不能为空") List<@Positive(message = "应用ID必须为正数") Long> applicationIds,
            @Parameter(description = "项目ID", required = true)
            @RequestParam("projectId") @NotNull(message = "项目ID不能为空") @Positive(message = "项目ID必须为正数") Long projectId) {
        Boolean result = projectService.removeApplicationsFromProject(applicationIds, projectId);
        return Response.success(result);
    }

    /**
     * 获取项目下的应用数量
     * 
     * @param projectId 项目ID
     * @return 应用数量
     */
    @GetMapping("/app-count/{projectId}")
    @Operation(summary = "获取项目应用数量", description = "获取指定项目下的应用数量")
    @ApiOperationLog(description = "获取项目应用数量")
    public Response<Long> getApplicationCountByProjectId(
            @Parameter(description = "项目ID", required = true)
            @PathVariable("projectId") @NotNull(message = "项目ID不能为空") @Positive(message = "项目ID必须为正数") Long projectId) {
        Long result = projectService.getApplicationCountByProjectId(projectId);
        return Response.success(result);
    }
}